#include "Precompiled.h"
#include "Scene.h"
#include "EntityLogicManager.h"
#include "EntityLogicPair.h"

namespace Game {
namespace Common {

RTTI_IMPL(Scene, DrawableEntity);

Scene::Scene() :
        drawableGameEntities(new Collection<DrawableEntity*>()),
        gameEntities(new Collection<Entity*>()),
        entityLogic(new Collection<EntityLogicPair*>()),
        gameLogicManager(NULL) {
}

Scene::~Scene() {
    SAFE_DELETE(this->drawableGameEntities);
    SAFE_DELETE(this->gameEntities);
    this->ClearEntityLogic();
    SAFE_DELETE(this->entityLogic);
}

int Scene::GetCount() {
    return this->gameEntities->GetCount();
}

void Scene::Add(Entity* item) {
    this->gameEntities->Add(item);
    this->AddEntityLogic(item);

    if (item->GetRTTI().DerivesFrom(DrawableEntity::rtti)) {
        this->drawableGameEntities->Add(static_cast<DrawableEntity*>(item));
    }
}

void Scene::Clear() {
    this->gameEntities->Clear();
    this->ClearEntityLogic();
    this->drawableGameEntities->Clear();
}

Entity* Scene::GetItem(int index) {
    return this->gameEntities->GetItem(index);
}

int Scene::IndexOf(Entity* item) {
    return this->gameEntities->IndexOf(item);
}

bool Scene::Remove(Entity* item) {
    bool result = this->gameEntities->Remove(item);
    if (result) {
        this->RemoveEntityLogic(item);
        if (item->GetRTTI().DerivesFrom(DrawableEntity::rtti)) {
            this->drawableGameEntities->Remove(static_cast<DrawableEntity*>(item));
        }
    }

    return result;
}

void Scene::RemoveAt(int index) {
    Entity* gameEntity = this->gameEntities->GetItem(index);
    if (gameEntity != NULL) {
        this->Remove(gameEntity);
    }
}

EntityLogicManager* Scene::GetEntityLogicManager() const {
    return this->gameLogicManager;
}

void Scene::SetEntityLogicManager(EntityLogicManager* val) {
    this->gameLogicManager = val;
}

Collection<EntityLogicPair*>* Scene::GetEntityLogic() const {
    return this->entityLogic;
}

Collection<EntityRenderPair*>* Scene::GetEntityRender() const {
    return this->entityRender;
}

void Scene::AddEntityLogic(Entity* item) {
    IEntityLogic* gameLogic = this->gameLogicManager->GetEntityLogic(item->GetRTTI());
    EntityLogicPair* pair = new EntityLogicPair(item, gameLogic);
    this->entityLogic->Add(pair);
}

void Scene::ClearEntityLogic() {
    CollectionIterator<EntityLogicPair*> it(this->entityLogic);
    for (; it(); ++it) {
        EntityLogicPair* pair = *it;
        SAFE_DELETE(pair);
    }

    this->entityLogic->Clear();
}

void Scene::RemoveEntityLogic(Entity* item) {
    CollectionIterator<EntityLogicPair*> it(this->entityLogic);
    for (; it(); ++it) {
        EntityLogicPair* pair = *it;
        if (pair->GetGameEntity() == item) {
            this->entityLogic->Remove(pair);
            break;
        }
    }
}


}
}
